<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件生命周期</title>
    <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="app">

</div>
</body>
</html>
<script type="text/babel">
    let app=document.getElementById('app');

    /*
    组件的生命周期可分成三个状态：
    Mounting：已插入真实 DOM
    Updating：正在被重新渲染
    Unmounting：已移出真实 DOM
    生命周期的方法一共有七个 组件在不同状态下会自动调用这些方法!

    注意constructor(构造函数)和render(渲染)也是由路由自动调用的
    * */
    class Root extends React.Component{
        constructor(props) {
            super(props);
            this.state={
                root:"这是root的值"
            }
        }
        render() {
            return <fieldset>
                <legend><h2>root</h2></legend>
                <button onClick={this.oneclick.bind(this)}>点击修改值</button>
                <Child1 name={this.state.root}/>
            </fieldset>
        }
        oneclick(){
            this.setState({
                root:"值被修改了"
            })
        }
    }

    class Child1 extends React.Component{
        constructor(prpos) {
            super(prpos);
            console.log("constructor函数触发了")
            this.state={
                childMsg:"hello",
                Obj:{name:"张三",age:"14"},
            }
        }
        //组件渲染视图时触发,在整个组件生命周期中会调用多次!!setState会让render重新被调用! 在该方法中也无法获取元素!可以访问props
        render() {
            console.log("render走了")
            return <fieldset>
                <legend>
                    <h2>child1</h2>
                </legend>
                <p>state的值{this.state.childMsg}</p>
                <p>props的值{this.props.name}</p>
                <p>Obj的值:{this.state.Obj.name},{this.state.Obj.age}</p>
                <input ref="in1"/>
                <button onClick={this.oneClick.bind(this)}>点击改变</button>
            </fieldset>
        }
        oneClick(){
            let OBJ1=this.state.Obj;
            OBJ1.name="李四";
            this.setState({
                childMsg:"改变了",
                Obj:OBJ1,
            })
        }
    //    组件将要被挂载时触发,此时可以获取state数据但是无法获取元素
        componentWillMount() {
            console.log("componentWillMount触发了!!!",this.state.childMsg)
        };
        componentDidMount() {
            console.log("componentDidMount组件挂载完毕方法触发",this.props.name,this.state.childMsg,this.refs)
        };
    //    当组件接收到一个新的props时会触发该函数,该方法在第一次组件初始化时不会触发,newProps参数储存的时最新的props对象
        componentWillReceiveProps(newtProps) {
            console.log("这是componentWillReceiveProps的值改变",newtProps)
        };
    //    是否允许组件中的(props和state)更新,当react检测到props或者state需要更新时,会触发该函数进行询问,如果返回值是false则不能更新操作!如果返回值为true,则可以顺利进行更新操作!
    //    注意:该函数紫瑶见到props和state被赋值,就会触发,并且重新渲染页面,并不会判断新值和旧值的关系,如果新赋的值与旧值一样,就没有重新渲染页面的 必要!
    //     我们可以通过判断上一次的值和当前的新值是否相等来决定是否重新渲染页面.
    //    但是要注意:如果值的类型是非原始类型(例如数组)
shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate")
    if (this.props.name!=nextProps.name||this.state.childMsg!=nextState.childMsg||this.state.Obj!=nextState.Obj){
        return true;
    }else {
        return false;
    }
};
        //组件将要进行更新 当shouldComponentUpdate的返回值是true才会执行!!!两个参数是将要更改的props和state的新值! 此时,正在显示的props和state还未改变
        componentWillUpdate(nextProps, nextState) {
            console.log('Component WILL UPDATE!');
        }
        //组件更新完毕,两个参数是props和state修改之前的旧值,此时再次this.props和this.state 他们已经修改完毕
        componentDidUpdate(prevProps, prevState) {
            console.log('Component DID UPDATE!')
        }
        //组件将要被销毁时触发,我们一般在该事件中!移除监听,计时器,清除缓存,保存必要数据等收尾工作
        componentWillUnmount() {
            console.log('Component WILL UNMOUNT!')
        }
    }
    ReactDOM.render(<Root/>,app)
</script>